package com.example.selflearning.service.ehcache;
import com.example.selflearning.entity.UserEntity;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.UserManagedCache;
import org.ehcache.config.builders.UserManagedCacheBuilder;
import org.ehcache.spi.loaderwriter.BulkCacheLoadingException;
import org.ehcache.spi.loaderwriter.BulkCacheWritingException;
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 * Created by yangjingzhi on 2019/5/21.
 */
@Slf4j
public class CacheThroughUserService {
    private UserManagedCache<String, UserEntity> cache;

    public CacheThroughUserService() {
        cache = UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, UserEntity.class).withLoaderWriter(new CustomLoaderWriter())
                .build(true);
    }

    public UserEntity findUser(String id) {
        UserEntity result = cache.get(id);
        if (result == null) {
           log.info("can't find user in cache!");
        } else {
            log.info("get user from cache: {}" , id);
        }
        return result;
    }
    public UserEntity updateUser(String id, String info) {
        UserEntity user = new UserEntity(id, info);
        cache.put(id, user);
        return user;
    }
    public boolean deleteUser(String id) {
        cache.remove(id);
        return true;
    }

    public static void main(String[] args) throws Exception {
        final CacheThroughUserService service = new CacheThroughUserService();
        ExecutorService executorService = Executors.newFixedThreadPool(30);
        for (int i = 0; i < 3; i++) {
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("1");
                }
            });
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("2");
                }
            });
            executorService.execute(new Runnable() {
                public void run() {
                    service.findUser("3");
                }
            });
        }
        executorService.shutdown();
        executorService.awaitTermination(5, TimeUnit.SECONDS);
        System.out.println("---------------------------------");
        service.updateUser("1", "new info ...");
        service.findUser("1");
        service.deleteUser("1");
        service.findUser("1");
    }

    private static class CustomLoaderWriter implements CacheLoaderWriter<String, UserEntity> {
        @Override
        public UserEntity load(String s) throws Exception {
           log.info("::load user by id: " + s);
            Thread.sleep(1000);
            if (s == null || s.equals("1")) {
                return new UserEntity.NullUser();
            }
            return new UserEntity(s, "info ...");
        }

        @Override
        public Map<String, UserEntity> loadAll(Iterable<? extends String> iterable) throws BulkCacheLoadingException, Exception {
            System.out.println("::load user by ids: " + iterable);
            return null;
        }

        @Override
        public void write(String s, UserEntity userEntity) throws Exception {
            log.info("::update user by id:{} " , s);
        }

        @Override
        public void writeAll(Iterable<? extends Map.Entry<? extends String, ? extends UserEntity>> iterable) throws BulkCacheWritingException, Exception {
            log.info("::update user by ids");
        }

        @Override
        public void delete(String s) throws Exception {
            log.info("::delete user by id: " + s);
        }

        @Override
        public void deleteAll(Iterable<? extends String> iterable) throws BulkCacheWritingException, Exception {
            System.out.println("::delete user by ids");
        }
    }
}
